#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <semaphore.h>

template <typename T> // 线程安全的阻塞队列
class CircularQueue{
public:
    CircularQueue(size_t cap)
        : _cap(cap), _v(cap), _head(0), _tail(0)
    {
        pthread_mutex_init(&_mutex, nullptr);   // 初始化互斥锁
        sem_init(&_filled_slots, 0, 0);         // 初识时候没有数据
        sem_init(&_empty_slots, 0, cap);        // 初始时所有槽位为空          
    }

    // 生产者：向队列添加数据
    void Push(const T& item)
    {
        sem_wait(&_empty_slots);    // 等待空槽位
        pthread_mutex_lock(&_mutex);
        _v[_tail] = item;
        _tail = (_tail + 1) % _cap;

        std::cout << "Produced: " << item << std::endl;
        pthread_mutex_unlock(&_mutex);
        sem_post(&_filled_slots);   // 增加已填充槽位
    }

    // 消费者：向队列取出数据
    T Pop()
    {
        sem_wait(&_filled_slots);
        pthread_mutex_lock(&_mutex);
        T item = _v[_head];
        _head = (_head + 1) % _cap;

        std::cout << "Consumed: " << item << std::endl;
        pthread_mutex_unlock(&_mutex);
        sem_post(&_empty_slots);   // 增加空槽位
        return item;
    }


    ~CircularQueue()
    {
        pthread_mutex_destroy(&_mutex);
        sem_destroy(&_filled_slots);
        sem_destroy(&_empty_slots);
    }

private:   
    std::vector<T> _v;           // 队列
    size_t _cap;                // 最大容量
    size_t _head;               // 对头指针
    size_t _tail;               // 队尾指针
    pthread_mutex_t _mutex;     // 互斥锁
    sem_t _filled_slots;        // 已填充槽位信号量     
    sem_t _empty_slots;         // 空槽位信号量
};



void *producer(void *args) { // 生产者线程函数
    CircularQueue<int> *v = static_cast<CircularQueue<int>*>(args);
    for(int i = 1; i <= 7; i++){
        v->Push(i); // 生产数据
        sleep(1);
    }
    return nullptr;
}

void *consumer(void *args){ // 消费者线程函数
    CircularQueue<int> *v = static_cast<CircularQueue<int>*>(args);
    for(int i = 1; i <= 7; i++){
        int item = v->Pop();    // 消费数据
        sleep(2);               
    }
    return nullptr;
}

int main()
{
    CircularQueue<int> v(3); // 创建一个容量为 3 的阻塞队列

    pthread_t producer_thread, consumer_thread;
    pthread_create(&producer_thread, nullptr, producer, &v);
    pthread_create(&consumer_thread, nullptr, consumer, &v);

    pthread_join(producer_thread, nullptr);
    pthread_join(consumer_thread, nullptr);

    return 0;
}

